package biz

import (
	"t11Lib/t11Errors"
	"t11Lib/t11Log"
	"t11Lib/t11Model"
	"t11Lib/t11Util"
	"time"
	"亚太-iot-服务器/models"
)
import "github.com/astaxie/beego/cache"

type userIdCache struct {
	c cache.Cache
}

var UserIdCache = func() *userIdCache {
	ret := &userIdCache{}
	bm, err := cache.NewCache("memory", `{"interval":60}`)
	if err != nil {
		panic(err)
	}
	ret.c = bm
	return ret
}()

func (self *userIdCache) CacheUserId(user *models.JwtToken, userId string) {
	self.c.Put(userId, user, time.Minute*30)
}

func (self *userIdCache) GetUserById(userId string) *models.JwtToken {
	val := self.c.Get(userId)
	if val == nil {
		return nil
	}
	u, ok := val.(*models.JwtToken)
	if ok {
		return u
	}
	return nil
}

type userBiz struct{}

var UserBiz userBiz

func (self userBiz) DeleteDeviceAdmin(conn *t11Model.DbConn, devId string, user *models.JwtToken) t11Errors.T11Error {

	if devId == "" {
		return nil
	}
	//删除device
	return t11Model.Transacrtion(conn, func() t11Errors.T11Error {

		//删除旧设备的userKv
		if e := models.UserKvDao.DeleteDeviceKvByDevId(conn, []string{devId}); e != nil {
			return e
		}
		//删除旧设备的kv
		if e := models.DeviceKvDao.DeleteByDevId(conn, []string{devId}); e != nil {
			return e
		}

		//删除旧设备的映射关系
		tokens, e := models.UserDeviceDao.GetTokensByDeviceId(conn, devId)
		if e != nil {
			return e
		}
		for _, token := range tokens {
			//TODO:发送设备删除的消息给相关的用户
			t11Log.Debuglnf("%v", token)
			//weixinOperator.TemplateMsg.SendUserDeleteMsg()
		}

		if e := models.UserDeviceDao.DeleteByDevId(conn, []string{devId}); e != nil {
			return e
		}
		//删除旧的设备
		if _, e := models.DeviceDao.Delete(conn, devId); e != nil {
			return e
		}
		return nil
	})
}

func (self userBiz) DeleteDeviceShare(conn *t11Model.DbConn, devId string, user *models.JwtToken) t11Errors.T11Error {

	//删除device
	return t11Model.Transacrtion(conn, func() t11Errors.T11Error {

		//删除userDeviceKv
		e := models.UserKvDao.DeleteDeviceKvByUser(conn, devId, user)
		if e != nil {
			return e
		}
		return models.UserDeviceDao.Delete(conn, devId, user)
	})
}

func (self userBiz) DeleteDevice(conn *t11Model.DbConn, devId string, user *models.JwtToken) t11Errors.T11Error {

	if devId == "" {
		return nil
	}

	userDevice, err := models.UserDeviceDao.Get(conn, devId, user)
	if err != nil {
		return err
	}

	// 根据类型来判断是删除管理员还是删除分享用户
	if userDevice.BindType == "admin" {
		t11Log.Debuglnf("删除管理员用户")
		err = self.DeleteDeviceAdmin(conn, devId, user)
	} else {
		t11Log.Debuglnf("删除分享用户")
		err = self.DeleteDeviceShare(conn, devId, user)
	}
	return err
}

func (self userBiz) ListData(conn *t11Model.DbConn, wxUser *models.JwtToken) (map[string]interface{}, t11Errors.T11Error) {
	ret := make(map[string]interface{})

	//获取网关列表
	gws, err := GatewayBiz.GetList(conn, wxUser)
	if err != nil {
		return nil, err
	}
	ret["gateways"] = gws

	//门锁列表
	devs, err := GatewayBiz.ListDevices(conn, wxUser.ToId())
	if err != nil {
		return nil, err
	}
	ret["devices"] = devs

	//device kv信息
	kvs, err := DevBiz.ListDeviceKvs(conn, devs)
	if err != nil {
		return nil, err
	}
	ret["deviceKvs"] = kvs

	//网关日志信息
	devLogs, err := DevBiz.ListLogs(conn, devs)
	if err != nil {
		return nil, err
	}
	ret["devLogs"] = devLogs

	//用户网关级别kv
	userGwKvs, err := GatewayBiz.GetUserGatewayKvs(conn, wxUser)
	if err != nil {
		return nil, err
	}
	ret["userGatewayKvs"] = userGwKvs

	//用户设备级别kv
	userDevKvs, err := DevBiz.GetUserDeviceKvs(conn, wxUser)
	if err != nil {
		return nil, err
	}
	ret["userDeviceKvs"] = userDevKvs

	// 获取设备的绑定类型
	devsType, err := DevBiz.GetDeviceType(conn, wxUser)
	if err != err {
		return nil, err
	}
	ret["devsType"] = devsType

	// 获取保修卡信息
	// 管理员用户和分享用户都能看到保修卡信息
	guarantee, err := DevBiz.ListGuarantees(conn, devs)
	if err != nil {
		return nil, err
	}
	ret["guarantee"] = guarantee

	return ret, err
}

func (self userBiz) SetDeviceKv(conn *t11Model.DbConn, user *models.JwtToken, devId, key, val string) t11Errors.T11Error {
	//不检查用户是否拥有设备
	if val == "" {
		//删除设备
		return models.UserKvDao.DeleteDeviceKvByUserAndKey(conn, devId, user, key)
	} else {
		//添加或修改val
		return models.UserKvDao.CreateOrModifyDeviceKv(conn, user, devId, key, val)
	}
}

func (self userBiz) SetGatewayKv(conn *t11Model.DbConn, user *models.JwtToken, gwId, key, val string) t11Errors.T11Error {
	if val == "" {
		return models.UserKvDao.DeleteGatewayKvByUserAndKey(conn, user, gwId, key)
	} else {
		return models.UserKvDao.CreateOrModifyGatewayKv(conn, user, gwId, key, val)
	}
}

//创建或更新保修卡
func (self userBiz) CreateOrUpdateGuarantee(conn *t11Model.DbConn, user *models.JwtToken, dev string, info string) t11Errors.T11Error {
	return models.GuranteeDao.CreateOrUpdate(conn, user.ToId(), dev, info)
}

func (self userBiz) CreateDevAndUserDev(conn *t11Model.DbConn, user *models.JwtToken, dev string) t11Errors.T11Error {

	bindType, err := self.BindDeviceOfType(conn, dev)
	if err != nil || bindType != "admin" {
		return err
	}

	// 该接口只创建管理员用户, 不创分享用户
	_, err = models.DeviceDao.Create(conn, &models.Device{BaseMdl: t11Model.BaseMdl{Id: dev}})
	if err != nil {
		return err
	}

	return models.UserDeviceDao.Create(conn, dev, user.ToId(), user.ToId(), bindType)
}

func (self userBiz) DeleteGatewayForDevice(conn *t11Model.DbConn, user *models.JwtToken, dev string) t11Errors.T11Error {
	if _, err := models.UserDeviceDao.Get(conn, dev, user); err != nil {
		return err
	}
	return models.DeviceDao.SetDeviceGateway(conn, dev, "")
}

func (self userBiz) BindDeviceOfType(conn *t11Model.DbConn, devId string) (string, t11Errors.T11Error) {

	isHasAdmin := false
	tokens, _ := models.UserDeviceDao.GetTokensByDeviceId(conn, devId)

	if len(tokens) == 0 {
		return "admin", nil
	}

	// 判断是否存在管理员用户
	for _, token := range tokens {
		user, _ := models.UserDeviceDao.Get(conn, devId, token)
		if user.BindType == "admin" {
			isHasAdmin = true
			break
		}
	}

	if isHasAdmin {
		return "share", nil
	}

	// 管理员用户不存在，删除所有用户，并重新注册管理员
	_ = models.UserKvDao.DeleteDeviceKvByDevId(conn, []string{devId})
	_ = models.UserDeviceDao.DeleteByDevId(conn, []string{devId})

	return "admin", nil
}

func (self userBiz) ListShareDevices(conn *t11Model.DbConn, token *models.JwtToken, devId string) ([]map[string]interface{}, t11Errors.T11Error) {

	var ret []map[string]interface{}

	users, err := models.UserDeviceDao.GetUsersByDeviceId(conn, devId)
	if err != nil {
		return nil, err
	}

	// 剔除管理员用户
	for index, user := range users {

		if user.BindType == "admin" {
			users = append(users[:index], users[index+1:]...)
			break
		}
	}

	for _, user := range users {

		var devInfo = make(map[string]interface{})
		token := models.ParseJwtToken(user.UserId)
		openId := token.UserId
		appId := token.AppId
		wxUser, err := models.WxUserDao.GetByOpenId(conn, appId, openId)
		if err != nil {
			return nil, err
		}

		userId := []byte(user.UserId)
		devInfo["userId"] = t11Util.BytesToHexStringWithoutSpace(t11Util.Md5(userId))
		devInfo["nickName"] = wxUser.Nickname
		devInfo["headImg"] = wxUser.HeadImgUrl
		devInfo["createTime"] = user.Created
		devInfo["devId"] = devId
		ret = append(ret, devInfo)
	}

	return ret, nil
}





